home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / prolog / sbprolog / v3 / sim.lha / sim / loader.c < prev    next >
C/C++ Source or Header  |  1990-04-12  |  21KB  |  704 lines

  1. /************************************************************************
  2. *                                    *
  3. * The SB-Prolog System                            *
  4. * Copyright SUNY at Stony Brook, 1986; University of Arizona, 1987    *
  5. *                                    *
  6. ************************************************************************/
  7.  
  8. /*-----------------------------------------------------------------
  9. SB-Prolog is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY.  No author or distributor
  11. accepts responsibility to anyone for the consequences of using it
  12. or for whether it serves any particular purpose or works at all,
  13. unless he says so in writing.  Refer to the SB-Prolog General Public
  14. License for full details.
  15.  
  16. Everyone is granted permission to copy, modify and redistribute
  17. SB-Prolog, but only under the conditions described in the
  18. SB-Prolog General Public License.   A copy of this license is
  19. supposed to have been given to you along with SB-Prolog so you
  20. can know your rights and responsibilities.  It should be in a
  21. file named COPYING.  Among other things, the copyright notice
  22. and this notice must be preserved on all copies. 
  23. ------------------------------------------------------------------ */
  24. /* loader.c */
  25.  
  26. #include "sim.h"
  27. #include "inst.h"
  28. #include "aux.h"
  29.  
  30. #define GET_DATA(x,y)  (y*sizeof(*x) - fread(x,sizeof(char),y*sizeof(*x),fp))
  31. #define PUT_DATA(x,y)  (fwrite(x, sizeof(char), y*sizeof(*x), fp)/sizeof(*x))
  32.     /* GET_DATA and PUT_DATA are defined in this way to avoid byte
  33.        ordering problems when words are written out -- this way we
  34.        write things out,  and read them in,  a byte at a time.    */
  35. #define ST_PTRPTRPSC(i_addr) \
  36.    *(LONG_PTR *)i_addr = reloc_table[*(LONG_PTR)i_addr];
  37.  
  38. #define ST_PTRPSC(i_addr)    \
  39.    *(LONG_PTR)i_addr = *reloc_table[*(LONG_PTR)i_addr];
  40.  
  41. static WORD_PTR inst_addr;
  42. static LONG_PTR hptr;
  43. static LONG_PTR reloc_table[500];
  44. static LONG_PTR last_text;
  45.  
  46. WORD   eof_flag;
  47. LONG   psc_bytes, text_bytes, index_bytes, magic;
  48.  
  49. int    (*load_routine[20])();
  50.  
  51. static FILE *fp;
  52. static BYTE perm = PERM;
  53.  
  54. extern fread();
  55. extern LONG_PTR reloc_addr();        /* actually it is defined below */
  56.  
  57. /****************************************************************************/
  58. /*                                                                          */
  59. /* fix_bb4: fixes the byte-backwards problem.  It is passed a pointer to a  */
  60. /* sequence of 4 bytes read in from a file as bytes.  It then converts      */
  61. /* those bytes to represent a number.  This code works for any machine, and */
  62. /* makes the byte-code machine independent.                                 */
  63. /*                                                                          */
  64. /****************************************************************************/
  65. fix_bb4(lptr)
  66. BYTE_PTR lptr;
  67. {
  68.    LONG_PTR numptr = (LONG_PTR)lptr;
  69.  
  70.    *numptr = (((((*lptr << 8) | *(lptr+1)) << 8) | *(lptr+2)) << 8) | *(lptr+3);
  71. }
  72.  
  73. /****************************************************************************/
  74. /*                                                                          */
  75. /* fix_bb2: fixes the byte-backwards problem.  It is passed a pointer to a  */
  76. /* sequence of 2 bytes read in from a file as bytes.  It then converts      */
  77. /* those bytes to represent a number.  This code works for any machine, and */
  78. /* makes the byte-code machine independent.                                 */
  79. /*                                                                          */
  80. /****************************************************************************/
  81. fix_bb2(lptr)
  82. BYTE_PTR lptr;
  83. {
  84.    WORD_PTR numptr = (WORD_PTR)lptr;
  85.  
  86.    *numptr = (*lptr << 8) | *(lptr+1);
  87. }
  88.  
  89. /****************************************************************************/
  90. /*                                                                          */
  91. /*    Load the file into permanent space, starting from "curr_fence".       */
  92. /* Data segment first (mixed psc entries and name strings), then text       */
  93. /* segment, ended with a virtual instruction "endfile <pointer>" where the  */
  94. /* pointer is a pointer to the next text segment (of another byte code      */
  95. /* file).                                                                   */
  96. /*                                                                          */
  97. /****************************************************************************/
  98. loader(file)
  99. CHAR_PTR file;
  100. {
  101.    CHAR_PTR restore;
  102.    WORD     err_msg;
  103.  
  104.    fp = fopen(file, "r");
  105.    if (fp == NULL)
  106.       return 10;
  107.    if (hitrace)
  108.       printf("\n     ...... loading file %s\n", file);
  109.  
  110.    while ((eof_flag = GET_DATA(&magic, 1)) == 0) {
  111.       if (eof_flag = GET_DATA(&psc_bytes, 1))
  112.      return 1;
  113.       if (eof_flag = GET_DATA(&text_bytes, 1))
  114.      return 1;
  115.       if (eof_flag = GET_DATA(&index_bytes, 1))
  116.      return 1;
  117.  
  118.       err_msg = load_syms();
  119.  
  120.       if (err_msg != 0) {
  121.          printf("error %d loading file %s: bad symbol table\n", err_msg, file);
  122.          exit(1);  /* eventually upper level routines will determine */
  123.       } else {
  124.          restore = curr_fence;
  125.          err_msg = load_text();
  126.          if (err_msg != 0) {
  127.             printf("error %d loading file %s: bad text segment\n", err_msg, file);
  128.             curr_fence = restore;
  129.             exit(1);  /* eventually upper level routines will determine */
  130.          } else {
  131.             err_msg = load_index();
  132.             if (err_msg != 0) {
  133.                printf("error %d in (index) loading file %s: bad index segment\n", err_msg, file);
  134.                curr_fence = restore;
  135.                exit(1);  /*eventually upper level routines will determine */
  136.             } else {
  137.                if (eof_flag = GET_DATA(inst_addr, 4))
  138.                   return eof_flag;
  139.                fix_bb2(inst_addr);
  140.                if (*inst_addr != endfile)
  141.                    *inst_addr = endfile;
  142.                inst_addr += 2;              /* skip opcode and pad */
  143.                *(LONG_PTR)inst_addr = 0;    /* force 0 address (LONG) */
  144.                last_text  = (LONG_PTR)inst_addr;
  145.                inst_addr += 2;
  146.                curr_fence = (CHAR_PTR)inst_addr;
  147.                if (curr_fence >= max_fence)
  148.                   quit("Program area overflow\n");
  149.             }
  150.          }
  151.       }
  152.    }
  153.    fclose(fp);
  154.    return 0;
  155. }  /* end of loader */
  156.  
  157. /*************************************************************************
  158. *                                                                        *
  159. * Load_syms is a function which loads a symbol table given in a byte     *
  160. * code file into an appropriate format in the pcs table.  As part of     *
  161. * its function it resolves entry points for byte code intructions (call  *
  162. * to relloc_addr), and maintains a tableau so that instructions          *
  163. * with indices into the pcs table may have those indices resloved before *
  164. * loading them in the intruction array (byte code program space).  The   *
  165. * intructions are loaded by a separate function.                         *
  166. * The function returns a short integer which is an error code.  Relevant *
  167. * error codes are listed below.                                          *
  168. *                                                                        *
  169. *      1: in load_syms: incomplete or missing psc count                  *
  170. *      2: in load_syms: incomplete or missing ep in record dec           *
  171. *      3: in load_syms: incomplete or missing arity in record dec        *
  172. *      4: in load_syms: incomplete or missing length in record dec       *
  173. *      5: in load_syms: incomplete or missing name in record dec         *
  174. *      8: can not open file                                              *
  175. *                                                                        *
  176. *************************************************************************/
  177. load_syms()
  178. {
  179.    CHAR     name[256];
  180.    LONG     ep_offset;
  181.    LONG     i = 0, j, count = 0;
  182.    BYTE     temp_len;
  183.    BYTE     temp_arity;
  184.    LONG_PTR insert();
  185.  
  186.    fix_bb4(&psc_bytes);       /* caller read psc_bytes, we just fix it */
  187.  
  188.    while (count < psc_bytes && eof_flag == 0) {
  189.       if (eof_flag = GET_DATA(&ep_offset, 1))
  190.      return 2;
  191.       fix_bb4(&ep_offset);
  192.       if (eof_flag = GET_DATA(&temp_arity, 1))
  193.      return 3;
  194.       if (eof_flag = GET_DATA(&temp_len, 1))
  195.      return 4;
  196.       if (eof_flag = GET_DATA(name, temp_len))
  197.      return 5;
  198.       reloc_table[i] = insert(name, temp_len, temp_arity, &perm);
  199.       set_temp_ep(*reloc_table[i], ep_offset);
  200.       count += temp_len + 6;
  201.       i++;
  202.    }
  203.  
  204.    for (j = 0; j < i; j++)
  205.       set_real_ep(*reloc_table[j], curr_fence);
  206.    pspace_used = ((LONG)curr_fence - (LONG)(pspace)) / 4;
  207.    return 0;
  208. }  /* end of load_syms */
  209.  
  210. /************************************************************************
  211. *                                                                       *
  212. * Load_text loads the byte code instruction from a byte code file to    *
  213. * the byte code program space.  References to indices to the pcs table  *
  214. * are resolved with the use of the macro st_index.  New index relies    *
  215. * on the symbol table array which is assigned values by load_syms.      *
  216. * The routine assumes the current length (8/18/84) of byte code         *
  217. * intructions when reading from the byte code file.                     *
  218. * The function returns a short integer which is a error code.  Relevant *
  219. * error codes are listed below.                                         *
  220. *                                                                       *
  221. *      6: in load_text: byte code Operands are non-existent             *
  222. *      7: in load_text: Illegal instruction from PIL file               *
  223. *      8: can not open file                                             *
  224. *                                                                       *
  225. ************************************************************************/
  226. load_text()
  227. {
  228.    WORD current_opcode = 0;
  229.    LONG count = 0;
  230.    WORD opval;
  231.  
  232.    /* set text segments chain */
  233.    if (inst_begin == 0) 
  234.       inst_begin = (WORD_PTR)curr_fence;
  235.    else 
  236.       *last_text = (LONG)curr_fence;
  237.  
  238.    inst_addr = (WORD_PTR)curr_fence;
  239.  
  240.    fix_bb4(&text_bytes);
  241.  
  242.    while (count < text_bytes &&
  243.       (eof_flag = GET_DATA(¤t_opcode, 1)) == 0) {
  244.       fix_bb2(¤t_opcode);
  245.  
  246.       *inst_addr++ = current_opcode;
  247.  
  248.       if (current_opcode >= 100) {
  249.          switch (current_opcode - 100) {
  250.             case 0 : opval = 0x05;  break;
  251.             case 1 : opval = 0x08;  break;
  252.             case 2 : opval = 0x11;  break;
  253.             case 3 : opval = 0x46;  break;
  254.             case 4 : opval = 0x05;  break;
  255.             case 5 : opval = 0x27;  break;
  256.             case 6 : opval = 0x27;  break;
  257.             case 7 : opval = 0x03;  break;
  258.             case 8 : opval = 0x07;  break;
  259.          }
  260.          (*load_routine[xxopcode[opval].type])();
  261.          count += xxopcode[opval].size;
  262.       } else {
  263.          (*load_routine[xxopcode[current_opcode].type])();
  264.          count += xxopcode[current_opcode].size;
  265.       }
  266.   }
  267.  
  268.   if (count != text_bytes)   
  269.      return 9;               /* missing instructions */
  270.    return 0;
  271. }  /* end of load_text */
  272.  
  273.  
  274. load_index()
  275. {
  276.    LONG     psc_offset, clause_no, temp_len;
  277.    LONG     count = 0;
  278.    LONG_PTR psc;
  279.    WORD_PTR gen_index();
  280.  
  281.    fix_bb4(&index_bytes);
  282.  
  283.    while (count < index_bytes && eof_flag == 0) {
  284.       if (eof_flag = GET_DATA(&psc_offset, 1))
  285.      return 10;
  286.       fix_bb4(&psc_offset);
  287.       psc = (LONG_PTR)*reloc_table[psc_offset];
  288.       if (eof_flag = GET_DATA(&clause_no, 1))
  289.      return 1;
  290.       fix_bb4(&clause_no);
  291.       if (eof_flag = get_index_tab(clause_no, &temp_len))
  292.      return eof_flag;
  293.       inst_addr = gen_index(clause_no, psc);
  294.       count += (8 + temp_len);
  295.    }
  296.    return 0;
  297. }
  298.  
  299.  
  300. get_index_tab(clause_no, lenptr)
  301. LONG     clause_no;
  302. LONG_PTR lenptr;
  303. {
  304.    LONG     hashval, size, j;
  305.    LONG     count = 0;
  306.    BYTE     type;
  307.    LONG     val;
  308.    LONG_PTR label, reloc_addr();
  309.  
  310.    hptr = hreg;
  311.    size = hsize(clause_no);
  312.    for (j = 0; j < size; j++) {
  313.       indextab[j].l = 0;
  314.       indextab[j].link = (LONG_PTR)(&(indextab[j].link));
  315.    }
  316.    for (j = 0; j < clause_no; j++) {
  317.       if (eof_flag = GET_DATA(&type, 1))
  318.      return 11;
  319.       switch (type) {
  320.         case 'i': if (eof_flag = GET_DATA(&val, 1))
  321.              return 12;
  322.                   fix_bb4(&val);
  323.           count += 9;
  324.                   break;
  325.         case 'l': /* val = UNTAGGED(list_str); */
  326.               val = *(LONG_PTR)UNTAGGED(list_str);
  327.                   count += 5;
  328.                   break;
  329.         case 'n': /* val = UNTAGGED(nil_sym); */
  330.                   val = *(LONG_PTR)UNTAGGED(nil_sym);
  331.                   count += 5;
  332.                   break;
  333.         case 's': if (eof_flag = GET_DATA(&val, 1))
  334.              return 12;
  335.                   fix_bb4(&val);
  336.           count += 9;
  337.                   /* val = (WORD)reloc_table[val]; */
  338.                   val = *reloc_table[val];
  339.                   break;
  340.         case 'c': if (eof_flag = GET_DATA(&val, 1))
  341.              return 12;
  342.                   fix_bb4(&val);
  343.           count += 9;
  344.                   /* val = (WORD)reloc_table[val]; */
  345.                   val = *reloc_table[val];
  346.                   break;
  347.       }
  348.       if (eof_flag = GET_DATA(&label, 1))
  349.      return 13;
  350.       fix_bb4(&label);
  351.       label = reloc_addr((LONG)label);
  352.       hashval = IHASH(val, size);
  353.       inserth(label, &indextab[hashval]);
  354.    }
  355.  
  356.    *lenptr = count;
  357.    return 0;
  358. }  /* end of get_index_tab */
  359.  
  360.  
  361. WORD_PTR gen_index(clause_no, psc_ptr)
  362. LONG        clause_no;
  363. PSC_REC_PTR psc_ptr;
  364. {
  365.    WORD_PTR ep1, ep2;
  366.    LONG     j, size;
  367.    LONG_PTR temp;
  368.  
  369.    size = hsize(clause_no);
  370.    ep1  = inst_addr;
  371.    *ep1++ = hash;             /* opcode 'hash' */
  372.    *ep1++ = size;
  373.    ep2 = inst_addr + 2 + 2 * size;
  374.    temp = GET_EP(psc_ptr) + 1;             /* here the hash table size is */
  375.    *temp++ = (LONG)(inst_addr + 2);        /* computed and inserted into  */
  376.    *temp = size;                           /* sob instructions            */
  377.    for (j = 0; j < size; j++) {
  378.       if (indextab[j].l == 0) {
  379.          *(LONG_PTR)ep1 = (LONG)trap_vector[0];
  380.      ep1 += 2;
  381.       } else  if (indextab[j].l == 1) {
  382.          *(LONG_PTR)ep1 = (LONG)*(indextab[j].link);
  383.      ep1 += 2;
  384.       } else {
  385.          /* otherwise create try/retry/trust instruction */
  386.          *(LONG_PTR)ep1 = (LONG)ep2;
  387.      ep1 += 2;
  388.          temp = (LONG_PTR)(indextab[j].link);
  389.          GEN_TRY(try, GET_ARITY(psc_ptr), *temp++, ep2);
  390.          while (*temp != (LONG)temp) {
  391.             temp = (LONG_PTR)*temp;
  392.             GEN_TRY(retry, GET_ARITY(psc_ptr), *temp++, ep2);
  393.          }
  394.          *(ep2 - 4) = trust;
  395.       }
  396.    }
  397.    return ep2;
  398. }
  399.  
  400.  
  401. inserth(label, bucket)
  402. LONG_PTR label;
  403. struct   hrec *bucket;
  404. {
  405.    LONG_PTR temp;
  406.  
  407.    bucket->l++;
  408.    temp = (LONG_PTR)&(bucket->link);
  409.    if (bucket->l > 1) {
  410.       temp = (LONG_PTR)*temp;
  411.       while ((LONG_PTR)*temp != temp)
  412.          temp = (LONG_PTR)*(++temp);
  413.    }
  414.    *temp = (LONG)hptr;
  415.    *hptr++ = (LONG)label;
  416.    *hptr++ = *temp + 4;     /* *hptr++ = (LONG)hptr; */
  417. }
  418.  
  419.  
  420. hsize(numentry)
  421. LONG numentry;
  422. {
  423.    LONG i, j, temp;
  424.  
  425.    temp = numentry + 1;
  426.  
  427. hashsod:
  428.    j = temp / 2 + 1;
  429.    for (i = 2; i <= j; i++) {
  430.       if (i != temp && (temp % i) == 0) {
  431.          temp++;
  432.          goto hashsod;
  433.       }
  434.    }
  435.    return temp;
  436. }
  437.  
  438. /************************************************************************
  439. *                                                                       *
  440. * Reloc_addr calculates the entry point of the code using the entry     *
  441. * point stored in the byte code file as an offset, and the stack        *
  442. * pointer curr_fence as the relative address.  Note trap vectors are    *
  443. * are indicated with a - 1, in the byte code file.                      *
  444. *                                                                       *
  445. ************************************************************************/
  446. LONG_PTR reloc_addr(offset)
  447. LONG offset;
  448. {
  449.    if (offset >= 0)
  450.       return (LONG_PTR)((LONG)curr_fence + offset);
  451.    else if (-(offset+1) <= MAXTRAPS)
  452.       return trap_vector[-(offset+1)];
  453.    else
  454.       return (LONG_PTR)((LONG)curr_fence + offset);
  455. }
  456.  
  457.  
  458. l_E()
  459. {
  460. }
  461.  
  462. l_P()      /* pad only, no operands */
  463. {
  464.    if (GET_DATA(inst_addr, 1))
  465.       quit("incomplete instruction\n");
  466.    inst_addr++;
  467. }
  468.  
  469. l_PSS()    /* pad; operand 1 = 2 bytes; operand 2 = 2 bytes */
  470. {
  471.    if (GET_DATA(inst_addr, 3))
  472.       quit("incomplete instruction\n");
  473.    else {
  474.       inst_addr++;
  475.       fix_bb2(inst_addr);
  476.       inst_addr++;
  477.       fix_bb2(inst_addr);
  478.       inst_addr++;
  479.    }
  480. }
  481.  
  482. l_PC()     /* pad; operand 1 = 4 bytes */
  483. {
  484.    if (GET_DATA(inst_addr, 3))
  485.       quit("incomplete instruction\n");
  486.    else {
  487.       inst_addr++;
  488.       fix_bb4(inst_addr);
  489.       ST_PTRPTRPSC(inst_addr);
  490.       inst_addr += 2;
  491.    }
  492. }
  493.  
  494. l_PL()     /* pad; operand 1 = 4 bytes (number) */
  495. {
  496.    if (GET_DATA(inst_addr, 3))
  497.       quit("incomplete instruction\n"); 
  498.    else {
  499.       inst_addr++;
  500.       fix_bb4(inst_addr);
  501.       inst_addr += 2;
  502.    }
  503. }
  504.  
  505. l_PW()     /* operand 1 = 4 bytes (index) */
  506. {
  507.    if (GET_DATA(inst_addr, 3))
  508.       quit("incomplete instruction\n"); 
  509.    else {
  510.       inst_addr++;
  511.       fix_bb4(inst_addr);
  512.       ST_PTRPSC(inst_addr);
  513.       inst_addr += 2;
  514.    }
  515. }
  516.  
  517. l_PA()     /* operand 1 = 4 bytes (address) */
  518. {
  519.    if (GET_DATA(inst_addr, 3))
  520.       quit("incomplete instruction\n"); 
  521.    else {
  522.       inst_addr++;
  523.       fix_bb4(inst_addr);
  524.       *(LONG_PTR)inst_addr = (LONG)reloc_addr(*(LONG_PTR)inst_addr);
  525.       inst_addr += 2;
  526.    }
  527. }
  528.  
  529. l_PWW()
  530. {
  531. }
  532.  
  533. l_S()      /* operand 1 = 2 bytes */
  534. {
  535.    if (GET_DATA(inst_addr, 1))
  536.       quit("incomplete instruction\n");
  537.    else {
  538.       fix_bb2(inst_addr);
  539.       inst_addr++;
  540.    }
  541. }
  542.  
  543. l_SSS()    /* operands 1, 2 & 3 = 2 bytes */
  544. {
  545.    if (GET_DATA(inst_addr, 3))
  546.       quit("incomplete instruction\n");
  547.    else {
  548.       fix_bb2(inst_addr);
  549.       inst_addr++;
  550.       fix_bb2(inst_addr);
  551.       inst_addr++;
  552.       fix_bb2(inst_addr);
  553.       inst_addr++;
  554.    }
  555. }
  556.  
  557. l_SC()     /* operand 1 = 2 bytes (index); operand 2 = 4 bytes */
  558. {
  559.    if (GET_DATA(inst_addr, 3))
  560.       quit("incomplete instruction\n"); 
  561.    else {
  562.       fix_bb2(inst_addr);
  563.       inst_addr++;
  564.       fix_bb4(inst_addr);
  565.       ST_PTRPTRPSC(inst_addr);
  566.       inst_addr += 2;
  567.    }
  568. }
  569.  
  570. l_SL()     /* operand 1 = 2 bytes (number); operand 2 = 4 bytes (reg) */
  571. {
  572.    if (GET_DATA(inst_addr, 3))
  573.       quit("incomplete instruction\n");
  574.    else {
  575.       fix_bb2(inst_addr);
  576.       inst_addr++;
  577.       fix_bb4(inst_addr);
  578.       inst_addr += 2;
  579.    }
  580. }
  581.  
  582. l_SW()     /* operand 1 = 2 bytes (index); operand 2 = 4 bytes */
  583. {
  584.    if (GET_DATA(inst_addr, 3))
  585.       quit("incomplete instruction\n");
  586.    else {
  587.       fix_bb2(inst_addr);
  588.       inst_addr++;
  589.       fix_bb4(inst_addr);
  590.       ST_PTRPSC(inst_addr);
  591.       inst_addr += 2;
  592.    }
  593. }
  594.  
  595. l_SA()     /* operand 1 = 2 bytes (reg); operand 2 = 4 bytes (address) */
  596. {
  597.    if (GET_DATA(inst_addr, 3))
  598.       quit("incomplete instruction\n"); 
  599.    else {
  600.       fix_bb2(inst_addr);
  601.       inst_addr++;
  602.       fix_bb4(inst_addr);
  603.       *(LONG_PTR *)inst_addr = (LONG_PTR)reloc_addr(*(LONG_PTR)inst_addr);
  604.       inst_addr += 2;
  605.    }
  606. }
  607.  
  608. l_SAA()    /* operand 1 = 2 bytes (reg); operands 2 & 3 = 4 bytes (addr) */ 
  609. {
  610.    if (GET_DATA(inst_addr, 5))
  611.       quit("incomplete instruction\n"); 
  612.    else {
  613.       fix_bb2(inst_addr);
  614.       inst_addr++;
  615.       fix_bb4(inst_addr);
  616.       *(LONG_PTR)inst_addr = (LONG)reloc_addr(*(LONG_PTR)inst_addr);
  617.       inst_addr += 2;
  618.       fix_bb4(inst_addr);
  619.       *(LONG_PTR)inst_addr = (LONG)reloc_addr(*(LONG_PTR)inst_addr);
  620.       inst_addr += 2;
  621.    }
  622. }
  623.  
  624. l_BBW()     /* operands 1 & 2 = 1 byte; operand 3 = 4 bytes */
  625. {
  626.    if (GET_DATA(inst_addr, 3))
  627.       quit("incomplete instruction\n");
  628.    else {
  629.       inst_addr++;
  630.       fix_bb4(inst_addr);
  631.       ST_PTRPSC(inst_addr);
  632.       inst_addr += 2;
  633.    }
  634. }
  635.  
  636. l_BBA()     /* operands 1 & 2 = 1 byte; operand 3 = 4 bytes (address) */
  637. {
  638.    if (GET_DATA(inst_addr, 3))
  639.       quit("incomplete instruction\n"); 
  640.    else {
  641.       inst_addr++;
  642.       fix_bb4(inst_addr);
  643.       *(LONG_PTR *)inst_addr = (LONG_PTR)reloc_addr(*(LONG_PTR)inst_addr);
  644.       inst_addr += 2;
  645.    }
  646. }
  647.  
  648. init_load_routine()
  649. {
  650.    load_routine[ E   ] = l_E;
  651.    load_routine[ P   ] = l_P;
  652.    load_routine[ PSS ] = l_PSS;
  653.    load_routine[ PC  ] = l_PC;
  654.    load_routine[ PL  ] = l_PL;
  655.    load_routine[ PW  ] = l_PW;
  656.    load_routine[ PA  ] = l_PA;
  657.    load_routine[ PWW ] = l_PWW;
  658.  
  659.    load_routine[ S   ] = l_S;
  660.    load_routine[ SSS ] = l_SSS;
  661.    load_routine[ SC  ] = l_SC;
  662.    load_routine[ SL  ] = l_SL;
  663.    load_routine[ SW  ] = l_SW;
  664.    load_routine[ SA  ] = l_SA;
  665.    load_routine[ SAA ] = l_SAA;
  666.    load_routine[ BBW ] = l_BBW;
  667.    load_routine[ BBA ] = l_BBA;
  668. }
  669.  
  670. dyn_loader(psc_ptr)
  671. PSC_REC_PTR psc_ptr;
  672. {
  673.    extern   CHAR_PTR getenv();
  674.    CHAR     s[256], s1[256], s3[256];
  675.    CHAR_PTR s2;
  676.    WORD     i, returnval;
  677.  
  678.    namestring(psc_ptr, s1);
  679.    if (*s1 == '/') 
  680.       return loader(s1);
  681.    else if (*s1 == '.') 
  682.       return loader(s1);
  683.    else {
  684.       /* printf("using dynamic loader! %s\n", s1); */
  685.       s2 = getenv("SIMPATH");
  686.       while (1) {
  687.          while (*s2 == ':' || *s2 == ' ')
  688.         s2++;
  689.          i = 0;
  690.          if (*s2 == '\0')    /* file not found */
  691.             return 1;
  692.          while (*s2 && *s2 != ' ' && *s2 != ':') 
  693.             s[i++] = *s2++;
  694.          s[i++] = '/';
  695.          s[i] = '\0';
  696.          scat(s, s1, s3);
  697.          returnval = loader(s3);
  698.  
  699.          if (returnval == 0)
  700.             return 0;
  701.       }
  702.    }
  703. }
  704.